﻿//==============================================================
// Level Class
// desc: represents a map level, complete with sprites, and 
//       collision objects.
// by:   T. Jared Smith
//==============================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Tank
{
    public enum mapTheme
    {
        Tron,
        Tundra
    }

    
    // Loads and initializes all sprites for the World
    public class Level
    {
        // Members        
        mapTheme theme;
        Sprite surface;        
        Rectangle worldSize;
        Rectangle playableArea;
        List<Vector2> spawnPoints;
        List<bool> availableSpawnPoints;
        Frame obstacleFrame;
        List<PickUp> pickUps;       //<-----ADDED BY JWK
        static Random random = new Random();
        List<Vector2> gridPoints;
        List<Sprite> obstacles;

        // Constructor
        public Level(mapTheme theme, Rectangle playable, Rectangle worldSz)
        {
            this.theme = theme;            
            // TODO - this sprites texture needs to be fixed so it has just the background images
            surface = new Sprite(new Vector2() , 0, 0, 0, "TronBase", theme.ToString());
            obstacles = new List<Sprite>();
            pickUps = new List<PickUp>();   //<-----ADDED BY JWK
            playableArea = playable;
            worldSize = worldSz;

            // Set spawn points (+310 px apart)
            spawnPoints = new List<Vector2>();         
            // Top Row
            spawnPoints.Add( new Vector2(40, 40)); // TODO
            spawnPoints.Add( new Vector2(440, 40)); // TODO
            spawnPoints.Add( new Vector2(840, 40)); // TODO
            spawnPoints.Add( new Vector2(1240, 40)); // TODO            
            // Bottom Row
            spawnPoints.Add( new Vector2(40, 680)); // TODO
            spawnPoints.Add( new Vector2(440, 680)); // TODO
            spawnPoints.Add( new Vector2(840, 680)); // TODO
            spawnPoints.Add( new Vector2(1240, 680)); // TODO            
             
            // Mark spawn points as available
            availableSpawnPoints = new List<bool>(10);
            ResetSpawnPoints();

            // Set location of obstacle on sprite sheet
            obstacleFrame = new Frame();
            obstacleFrame.x = 108;
            obstacleFrame.y = 1276;
            obstacleFrame.width = 164;
            obstacleFrame.height = 164;

            // Set coordinates used to spawn objects
            gridPoints = new List<Vector2>(28);
            while (true)
            {
                for (int i = 1; i < 8; i++)
                {
                    for (int j = 1; j < 5; j++)
                    {
                        gridPoints.Add(new Vector2(i * 160, (j * 160) - 40));
                    }
                }
                break;
            }

        }
        
        // Intitialize Sprites - Sprites will be placed in Rows/Columns
        public void InitSprites()
        {  
            // Randomly choose what objects to draw
            for (int i = 0; i < gridPoints.Count(); i++)  
            {
                int draw = random.Next(1, 3);           // Chance of spawning object
                if (draw == 1)  
                {
                    // Because bounding box sizes are unique for each shape, determine what shape to draw
                    // then set the size for each bounding box. TODO - this is not entirely accurate
                    SquareSpriteShape s;
                    int g = random.Next(1, 3);
                    // Dont draw Medium Rectangles(they are to close to the border)
                    if ( i < 7 || i > 20 )                                  
                    {
                        if (g == 1)
                        {
                            s = SquareSpriteShape.SQUARE;
                        }
                        else
                        {
                            s = SquareSpriteShape.SMALLRECT;
                        }
                    }
                    // Randomize shape
                    else
                    {
                        s = RandomShape();                                      
                    }

                    SquareSpriteColor c = RandomColor();                    // Randomize color
                    if (s.Equals(SquareSpriteShape.SQUARE))
                    {
                        obstacles.Add(new SquareSprite(gridPoints[i], 0, 0, 0, "New-Tron", "ob1", 80, 80, c, s));
                    }
                    else if (s.Equals(SquareSpriteShape.SMALLRECT))
                    {
                        obstacles.Add(new SquareSprite(gridPoints[i], 0, 0, 0, "New-Tron", "ob1", 46, 80, c, s));
                    }
                    else if (s.Equals(SquareSpriteShape.MEDRECT))
                    {
                        obstacles.Add(new SquareSprite(gridPoints[i], 0, 0, 0, "New-Tron", "ob1", 46, 146, c, s));
                    }
                    else if (s.Equals(SquareSpriteShape.LARGERECT))
                    {
                        obstacles.Add(new SquareSprite(gridPoints[i], 0, 0, 0, "New-Tron", "ob1", 46, 278, c, s));
                    }                    
                }
            }
        }


        // Update

        public void Update()
        {
            //if (pickUps.Count < 2)
            //{
            //    SpawnPickUps();
            //}
        }

        // Draw

        public void Draw(SpriteBatch sBatch)
        {
            // TODO - Draw map background - this is currently done in Game1.InitScenes() (where it is setup)
            // surface.Draw(sBatch);

            // Draw obstacles
            foreach (Sprite s in obstacles)
            {
                s.Draw(sBatch);
            }

            foreach (PickUp p in pickUps)
            {
                p.Draw(sBatch);
            }
        }

        //=============================================================
        // SpawnPickUps 
        // Desc: Adds two pick ups to a list.
        //=============================================================
        public void SpawnPickUps()
        {
            int buffer = 160;   // 2 x ( sqrt( 80**2  +  80**2 ) )= 226.27
            Vector2 coord = new Vector2(1280, 720);
            Vector2 prospect = new Vector2();

            // Place first random pick up
            prospect.X = random.Next(buffer, (int)coord.X - buffer);
            prospect.Y = random.Next(buffer, (int)coord.Y - buffer);
            pickUps.Add(new PickUp(prospect, 0, 0, 0, "Plasma", "plasma", 80, PICKUP.Plasma));

            prospect.X = random.Next(buffer, (int)coord.X - buffer);
            prospect.Y = random.Next(buffer, (int)coord.Y - buffer);
            pickUps.Add(new PickUp(prospect, 0, 0, 0, "Electro", "electro", 80, PICKUP.Electro));
        }

        //=============================================================
        // RandomColor
        // Desc: Randomly choose sprite color
        //=============================================================
        public SquareSpriteColor RandomColor()
        {
            int color = random.Next(1, 5);
            switch (color)
            {
                case 1:
                    return SquareSpriteColor.GREEN;                    
                case 2:
                    return SquareSpriteColor.BLUE;
                case 3:
                    return SquareSpriteColor.ORANGE;
                case 4:
                    return SquareSpriteColor.RED;
                default:
                    return SquareSpriteColor.RED;                
            }
        }

        //=============================================================
        // RandomShape
        // Desc: Randomly choose rectangular shape
        //=============================================================
        public SquareSpriteShape RandomShape()
        {
            int shape = random.Next(1, 5);
            switch (shape)
            {
                case 1:
                    return SquareSpriteShape.SQUARE;
                case 2:
                    return SquareSpriteShape.SMALLRECT;
                case 3:
                    return SquareSpriteShape.MEDRECT;
                //case 4:
                //    return SquareSpriteShape.LARGERECT;
                default:
                    return SquareSpriteShape.SQUARE;
            }
        }

        // Add one obstacle
        public void AddObstacles(Sprite sprite)
        {            
            obstacles.Add(sprite);
        }

        // Add many obstacles
        public void AddObstacles(List<Sprite> obs)
        {
            foreach (Sprite s in obs)
            {
                obstacles.Add(s);
            }
        }

        // Remove an obstacle
        public void RemoveObstacle(string s)
        {
            // TODO
        }

        // Reset Level
        public void ResetLevel()
        {            
            ResetSpawnPoints();
            pickUps = new List<PickUp>();       // Clear all pick ups   
            obstacles = new List<Sprite>();     // Clear all obstacles in level
            InitSprites();                      // Regenerate new obstacles 
        }

        // Reset Spawn Point availability
        public void ResetSpawnPoints()
        {
            availableSpawnPoints = new List<bool>();
            for (int i = 0; i < 8; i++)
            {                
                availableSpawnPoints.Add(true);
            }
        }

        // Return random spawn point
        public Vector2 GetSpawnPoint()
        {
            Random r = new Random();
            int i;
            int max = spawnPoints.Count;

            do
            {
                i = r.Next(0, max);                     // Choose a random index
            } while (availableSpawnPoints[i] == false);

            availableSpawnPoints[i] = false;            // Mark as unavailable
            return spawnPoints[i];                      // Return available point           
        }

        public Rectangle PlayableArea
        {
            get { return playableArea; }
        }

        public List<Sprite> GetLevelSprites()
        {
            return obstacles;
        }

        public Sprite Surface { get; set; }

        public List<Sprite> Obstacles
        {
            get { return obstacles; }
        }

    }

}
